package com.leyou.gateway.filter;

import com.leyou.common.auth.domain.Payload;
import com.leyou.common.auth.domain.UserInfo;
import com.leyou.common.auth.utils.JwtUtils;
import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exception.LyException;
import com.leyou.common.upload.Path;
import com.leyou.common.utils.CookieUtils;
import com.leyou.gateway.config.FilterProperties;
import com.leyou.gateway.config.JwtProperties;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.FORM_BODY_WRAPPER_FILTER_ORDER;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
@Slf4j
@Component
@EnableConfigurationProperties({JwtProperties.class,FilterProperties.class})
public class AuthFilter extends ZuulFilter {
    @Autowired
    private JwtProperties jwtProperties;
    @Autowired
    private FilterProperties filterProperties;

    //过滤执行的时机 在触发之前
    @Override
    public String filterType() {
        return PRE_TYPE;
    }
    //过滤器执行的顺序 数字越小刷新越靠前
    @Override
    public int filterOrder() {
        //在form请求体之后执行  -1+1
        return FORM_BODY_WRAPPER_FILTER_ORDER + 1;
    }
    //过滤器开关 如果当前方法返回值为true 表示过滤器执行
    @Override
    public boolean shouldFilter() {
        return true;
    }
    //过滤器内容
    @Override
    public Object run() throws ZuulException {
        log.info("网关过滤器   请求网关");
        //获取request 域
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();

        //校验白名单
        if(isWhite(request.getRequestURI())){
            log.info("网关过滤器   当前用户在白名单内 无需登陆");
            return null;
        }

        //需要登陆的 鉴权
        //获取token
        String token = CookieUtils.getCookieValue(request, jwtProperties.getUser().getCookieName());
        //判断token是否存在 也就是是否携带token
        if(StringUtils.isBlank(token)){
            //表示 不再继续访问微服务 但是会继续当前 过滤方法的执行
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(403); //spring 403 http 401 权限不足
            //终止当前方法的执行 但是会走微服务
            return null;
        }
        //获取用户信息
        Payload<UserInfo> payload = null;
        try {
            payload = JwtUtils.getInfoFromToken(token, jwtProperties.getPublicKey(), UserInfo.class);
        } catch (Exception e) {
            //表示 不再继续访问微服务 但是会继续当前 过滤方法的执行
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(403); //spring 403 http 401 权限不足
            //终止当前方法的执行 但是会走微服务
            return null;
        }
        UserInfo userInfo = payload.getUserInfo();
        Long id = userInfo.getId();
        String role = userInfo.getRole();
        String username = userInfo.getUsername();
        //将用户id添加到请求头中 继续下面的微服务
        ctx.addZuulRequestHeader(Path.USER_ID_KEY,id.toString());
        //将用户角色添加到请求头中继续下面的微服务
        ctx.addZuulRequestHeader(Path.USER_ROLE_KEY,role);
        log.info("网关过滤器  执行完成 跳转微服务");

        return null;
    }

    //检测白名单中是否有当前地址
    private boolean isWhite(String requestURI) {
        for (String allowPath : filterProperties.getAllowPaths()) {
            if(requestURI.contains(allowPath)){
                return true;
            }
        }
        return false;
    }
}
